import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ConfigService } from '@nestjs/config';
import { BaseService } from '@wwjCommon/base/base.service';
import { CacheService } from '@wwjCommon/cache/cache.service';
import { LoggingService } from '@wwjCommon/logging/logging.service';
import { UploadService } from '@wwjVendor/upload/upload.service';
import { PayService } from '@wwjVendor/pay/pay.service';
import { SmsService } from '@wwjVendor/sms/sms.service';
import { NoticeService } from '@wwjVendor/notice/notice.service';

@Injectable()
export class CoreAppCloudService extends BaseService<any> {
  private readonly logger = new Logger(CoreAppCloudService.name);

  constructor(
    @InjectRepository(Object)
    protected readonly repository: Repository<any>,
    private readonly cacheService: CacheService,
    private readonly configService: ConfigService,
    private readonly loggingService: LoggingService,
    private readonly uploadService: UploadService,
    private readonly payService: PayService,
    private readonly smsService: SmsService,
    private readonly noticeService: NoticeService,
  ) {
    super(repository);
  }

  /**
   * appCloudBuid
   * 对应 PHP: CoreAppCloudService_core::appCloudBuid()
   * 逻辑类型: undefined - undefined
   */
  async appCloudBuid(data: any[]) {
    // 基于PHP真实逻辑: appCloudBuid
    // PHP原文: $this->site_id = $data['site_id'];          $action_token = ( new CoreModuleService() )->getActionToken('appbuild', [ 'data' => [ 'product_key' => Bas...
this.site_id = data.site_id;

        const action_token = ( this.coreModuleService ).getActionToken('appbuild', [ data: [ product_key: BaseNiucloudClient.PRODUCT ) )];

        const app_config = this.coreAppService.getConfig(this.site_id);
        if (!app_config.app_name)) throw new BusinessException("请先配置应用名称");
        if (!app_config.uni_app_id)) throw new BusinessException("请先配置应用ID");
        if (!app_config.android_app_key)) throw new BusinessException("请先配置应用密钥");
        if (!app_config.application_id)) throw new BusinessException("请先配置应用包名");

        const wap_url = this.coreSysConfigService.getSceneDomain(this.site_id).wap_url;
        const map_config = ( this.coreConfigService ).getConfigValue(this.site_id, 'MAPKEY'];
        const build = [
            app_name: app_config.app_name,
            uni_app_id: app_config.uni_app_id,
            wechat_app_id: app_config.wechat_app_id,
            wechat_app_secret: app_config.wechat_app_secret,
            android_app_key: app_config.android_app_key,
            application_id: app_config.application_id,
            privacy_agreement: wap_url  + '/app/pages/auth/agreement?key=privacy&=',
            service_agreement: wap_url  + '/app/pages/auth/agreement?key=service&=',
            qq_map_key: map_config.key || '',
            amap_key: map_config.amap_key || '',
            version_name: data.version_name,
            version_code: data.version_code,
            cert: data.cert
        ];

        // 上传任务key
        const task_key = time();
        // 此次上传任务临时目录
        const temp_dir = runtime_path()  + 'build_app' . DIRECTORY_SEPARATOR . task_key;
        const package_dir = temp_dir . DIRECTORY_SEPARATOR  + 'package' . DIRECTORY_SEPARATOR;
        // uni
        const uni_dir = package_dir  + 'uni-app';

        dir_copy(this.root_path  + 'uni-app', uni_dir, exclude_dirs: [ 'node_modules', 'unpackage', 'dist' )];
        this.handleUniapp(uni_dir];
        // 替换env文件
        this.weappEnvReplace(uni_dir . DIRECTORY_SEPARATOR  + '.env.production');

        // 拷贝证书文件
        if (data.cert.type == 'private') {
            if (!file_exists(data.cert.file)) throw new BusinessException('证书文件不存在'];
            const cert_content = file_get_contents(data.cert.file];
            file_put_contents(package_dir  + 'cert.jks', cert_content);
  }

  /**
   * handleTabbar
   * 对应 PHP: CoreAppCloudService_core::handleTabbar()
   * 逻辑类型: undefined - undefined
   */
  async handleTabbar(compile_path: any[], addon_arr: any[]) {
    // 基于PHP真实逻辑: handleTabbar
    // PHP原文: $bottomList = array_column(( new DiyConfigService() )->getBottomList(), null, 'key');         $tabbarList = [];         if (empty($addon_arr)) {      ...
const bottomList = array_column(( this.diyConfigService ).getBottomList(), null, 'key'];
        const tabbarList = [];
        if (!addon_arr)) {
            foreach (bottomList as app_item) {
                array_push(tabbarList, ...app_item[ 'value' )[ 'list' )];
            }
  }

  /**
   * getAppCompileLog
   * 对应 PHP: CoreAppCloudService_core::getAppCompileLog()
   * 逻辑类型: undefined - undefined
   */
  async getAppCompileLog(timestamp: string) {
    // 基于PHP真实逻辑: getAppCompileLog
    // PHP原文: $result = [             'status' => '',             'build_log' => [],             'file_path' => '',             'fail_reason' => ''         ];      ...
const result = [
            status: '',
            build_log: [],
            file_path: '',
            fail_reason: ''
        ];

        const query = [
            authorize_code: this.auth_code,
            timestamp: timestamp
        ];
        const build_log = ( new CloudService(true, 'http://java.oss.niucloud.com/') ).httpGet('cloud/get_appbuild_logs?' . http_build_query(query)];
        result.build_log = build_log;

        if (typeof build_log.data) && typeof build_log.data[0)) && is_[build_log.data[0))) {
            const last = end(build_log.data[0)];
            if (last.code == 0) {
                result.status = 'fail';
                result.fail_reason = last.msg || '';
                return result;
            }
            if (last.percent == 100) {
                const result = this.buildSuccess(result, timestamp);
            }
  }

  /**
   * buildSuccess
   * 对应 PHP: CoreAppCloudService_core::buildSuccess()
   * 逻辑类型: undefined - undefined
   */
  async buildSuccess(result: any[], task_key: any[]) {
    // 基于PHP真实逻辑: buildSuccess
    // PHP原文: try {             $query = [                 'authorize_code' => $this->auth_code,                 'timestamp' => $task_key             ];            ...
try {
            const query = [
                authorize_code: this.auth_code,
                timestamp: task_key
            ];
            const chunk_size = 1 * 1024 * 1024;
            const temp_dir = 'upload' . DIRECTORY_SEPARATOR  + 'download' . DIRECTORY_SEPARATOR  + 'app' . DIRECTORY_SEPARATOR . task_key . DIRECTORY_SEPARATOR;
            if (!is_dir(temp_dir))  mkdirs(temp_dir);

            const build_task = Cache.get(this.cache_key . task_key) || [];

            if (!typeof build_task[ 'index' ))) {
                const response = ( new CloudService(true, 'http://java.oss.niucloud.com/') ).request('HEAD', 'cloud/apk_download?' . http_build_query(query), [
                    headers: [ Range: 'bytes=0-' ]
                ]];
                const length = response.getHeader('Content-range');
                const length = (int) explode("/", length[ 0 ))[ 1 ];
                const step = (int) ceil(length / chunk_size);
                const filename = response.getHeader('filename')[0];

                const build_task = Object.assign(build_task, [ step: step, index: 0, length: length, file_name: filename )];
                Cache.set(this.cache_key . task_key, build_task];
            } } } else {
                const file = temp_dir . build_task[ 'file_name' ];
                const file_resource = fopen(file, 'a');

                if (( build_task[ 'index' ) + 1 ) <= build_task[ 'step' ]) {
                    const start = build_task[ 'index' ] * chunk_size;
                    const end = ( build_task[ 'index' ) + 1 ) * chunk_size;
                    const end = min(end, build_task[ 'length' )];

                    const response = ( new CloudService(true, 'http://java.oss.niucloud.com/') ).request('GET', 'cloud/apk_download?' . http_build_query(query), [
                        headers: [ Range: "bytes={start}-{end}" ]
                    ]];
                    fwrite(file_resource, response.getBody()];
                    fclose(file_resource];

                    build_task[ 'index' ] += 1;
                    Cache.set(this.cache_key . task_key, build_task];

                    result.build_log[] = [ code: 1, action: '安装包下载中,已下载' . round(build_task[ 'index' ) / build_task[ 'step' ) * 100)  + '%', percent: '99' ];
                } } } else {
                    result.build_log[] = [ code: 1, action: '安装包下载中,已下载' . round(build_task[ 'index' ) / build_task[ 'step' ) * 100)  + '%', percent: '100' ];
                    result.status = 'success';
                    result.file_path = file;
                    Cache.set(this.cache_key . task_key, null);
                }
            }
  }

  /**
   * geAddonPackagePath
   * 对应 PHP: CoreAppCloudService_core::geAddonPackagePath()
   * 逻辑类型: undefined - undefined
   */
  async geAddonPackagePath(addon: string) {
    // 基于PHP真实逻辑: geAddonPackagePath
    // PHP原文: return $this->addon_path . $addon . DIRECTORY_SEPARATOR . 'package' . DIRECTORY_SEPARATOR;     }      public function generateSingCert(array $data) { ...
return this.addon_path . addon . DIRECTORY_SEPARATOR  + 'package' . DIRECTORY_SEPARATOR;
    }

    async generateSingCert(data) {
        const dname = "CN={data.cn}, OU={data.ou}, O={data.o}, L={data.l}, ST={data.st}, C={data.c}";
        const query = [
            key_alias: data.key_alias,
            key_password: data.key_password,
            store_password: data.store_password,
            limit: data.limit * 365,
            dname: dname
        ];
        const response = ( new CloudService(true, 'http://java.oss.niucloud.com/') ).request('GET', 'cloud/getcert?' . http_build_query(query)];
        const content_type = response.getHeaders().Content-Type[0];
        if (content_type == 'application/json') {
            const content = json_decode(response.getBody().getContents(), true];
            if (typeof content[ 'code' )) && content[ 'code' ] == 0) throw new BusinessException(content[ 'msg' )];
  }

  /**
   * generateSingCert
   * 对应 PHP: CoreAppCloudService_core::generateSingCert()
   * 逻辑类型: undefined - undefined
   */
  async generateSingCert(data: any[]) {
    // 基于PHP真实逻辑: generateSingCert
    // PHP原文: $dname = "CN={$data['cn']}, OU={$data['ou']}, O={$data['o']}, L={$data['l']}, ST={$data['st']}, C={$data['c']}";         $query = [             'key_a...
const dname = "CN={data.cn}, OU={data.ou}, O={data.o}, L={data.l}, ST={data.st}, C={data.c}";
        const query = [
            key_alias: data.key_alias,
            key_password: data.key_password,
            store_password: data.store_password,
            limit: data.limit * 365,
            dname: dname
        ];
        const response = ( new CloudService(true, 'http://java.oss.niucloud.com/') ).request('GET', 'cloud/getcert?' . http_build_query(query)];
        const content_type = response.getHeaders().Content-Type[0];
        if (content_type == 'application/json') {
            const content = json_decode(response.getBody().getContents(), true];
            if (typeof content[ 'code' )) && content[ 'code' ] == 0) throw new BusinessException(content[ 'msg' )];
  }

  /**
   * handleUniapp
   * 对应 PHP: CoreAppCloudService_core::handleUniapp()
   * 逻辑类型: undefined - undefined
   */
  async handleUniapp(dir: string) {
    // 基于PHP真实逻辑: handleUniapp
    // PHP原文: $site_addon = (new CoreSiteService())->getAddonKeysBySiteId($this->site_id);         $local_addon = ( new Addon() )->where([ [ 'status', '=', AddonDic...
const site_addon = this.coreSiteService.getAddonKeysBySiteId(this.site_id);
        const local_addon = ( this.addonService ).where([ [ 'status', '=', AddonDict.ON ) )).column('key');

        // 移除uniapp中该站点没有的插件
        const diff_addon = array_filter(array_map(function (key) use (site_addon) {
            if (!in_[key, site_addon)) return key;
  }

  /**
   * handlePageCode
   * 对应 PHP: CoreAppCloudService_core::handlePageCode()
   * 逻辑类型: undefined - undefined
   */
  async handlePageCode(compile_path: any, addon_arr: any) {
    // 基于PHP真实逻辑: handlePageCode
    // PHP原文: $pages = [];         foreach ($addon_arr as $addon) {             if (!file_exists($this->geAddonPackagePath($addon) . 'uni-app-pages.php')) continue;...
const pages = [];
        foreach (addon_arr as addon) {
            if (!file_exists(this.geAddonPackagePath(addon)  + 'uni-app-pages.php')) continue;
            const uniapp_pages = require this.geAddonPackagePath(addon)  + 'uni-app-pages.php';
            if (!uniapp_pages[ 'pages' ))) continue;

            const page_begin = strtoupper(addon)  + '_PAGE_BEGIN';
            const page_end = strtoupper(addon)  + '_PAGE_END';

            // 对0.2.0之前的版本做处理
            uniapp_pages[ 'pages' ] = preg_replace_callback('/(.*)(\\r\\n.*\/\/ PAGE_END.*)/s', function (match) {
                return match[ 1 ] . ( substr(match[ 1 ), -1) == ',' ? '' : ',' ) . match[ 2 ];
            }, uniapp_pages[ 'pages' ]];

            uniapp_pages[ 'pages' ] = str_replace('PAGE_BEGIN', page_begin, uniapp_pages[ 'pages' )];
            uniapp_pages[ 'pages' ] = str_replace('PAGE_END', page_end, uniapp_pages[ 'pages' )];
            uniapp_pages[ 'pages' ] = str_replace('{{addon_name}}', addon, uniapp_pages[ 'pages' )];

            pages[] = uniapp_pages[ 'pages' ];
  }

  /**
   * weappEnvReplace
   * 对应 PHP: CoreAppCloudService_core::weappEnvReplace()
   * 逻辑类型: undefined - undefined
   */
  async weappEnvReplace(env_file: string) {
    // 基于PHP真实逻辑: weappEnvReplace
    // PHP原文: $env = file_get_contents($env_file);         $env = str_replace("VITE_APP_BASE_URL=''", "VITE_APP_BASE_URL='" . (string) url('/', [], '', true) . 'api...
const env = file_get_contents(env_file);
        const env = str_replace("VITE_APP_BASE_URL=''", "VITE_APP_BASE_URL='" . (string) url('/', [), '', true)  + 'api/'  + ''", env];
        const env = str_replace("VITE_IMG_DOMAIN=''", "VITE_IMG_DOMAIN='" . (string) url('/', [), '', true)  + ''", env];
        const env = str_replace("VITE_SITE_ID = ''", "VITE_SITE_ID='" . this.site_id  + ''", env];
        file_put_contents(env_file, env);
    }

    /**
     * 获取APP编译日志
     * @param string timestamp
     * @return void
     */
    async getAppCompileLog(string timestamp)
    {
        const result = [
            status: '',
            build_log: [],
            file_path: '',
            fail_reason: ''
        ];

        const query = [
            authorize_code: this.auth_code,
            timestamp: timestamp
        ];
        const build_log = ( new CloudService(true, 'http://java.oss.niucloud.com/') ).httpGet('cloud/get_appbuild_logs?' . http_build_query(query)];
        result.build_log = build_log;

        if (typeof build_log.data) && typeof build_log.data[0)) && is_[build_log.data[0))) {
            const last = end(build_log.data[0)];
            if (last.code == 0) {
                result.status = 'fail';
                result.fail_reason = last.msg || '';
                return result;
            }
            if (last.percent == 100) {
                const result = this.buildSuccess(result, timestamp);
            }
  }
}
